#!/usr/bin/env python3
# -*- coding:utf-8 -*-
# @Time: 2019/3/3  21:30
# @Author: 余浪人
# @email: yulangren520@gmail.com

import random, hashlib, uuid, re
from datetime import datetime
from flask import request, jsonify, abort
from flask_login import current_user
from apps.lib.pwd_verify import check_password
from apps.lib.token import generate_token


def get_uuid_16():
    '''
    获取一个16位的UUID
    :return:
    '''
    data = str(uuid.uuid4())
    return ''.join(data.split('-')[:3])


def get_date_str():
    '''
    获取当前时间 格式化后
    :return:
    '''
    return datetime.now().strftime('%Y-%m-%d')


def get_date():
    '''
    :return: 当前日期
    '''
    return datetime.now()  # .strftime('%Y-%m-%d')


def gen_rnd_filename():
    '''
    :return: 获取当前时间
    '''
    filename_prefix = datetime.now().strftime('%Y%m%d%H%M%S')
    return '%s%s' % (filename_prefix, str(random.randrange(1000, 10000)))


def get_random(a, b):
    '''
    获取一个随机数
    :param a: start
    :param b: end
    :return: num
    '''
    return random.randint(a, b)


def random_click():
    '''
    获取一个点击数
    :param a: start
    :param b: end
    :return: num
    '''
    return random.randint(1, 1000)


def check_obj(obj):
    '''
    验证数据合法性
    :param obj: 查询对象
    :return:
    '''
    if obj is None:
        return abort(404)


def api_check_obj(obj):
    '''
    验证数据合法性
    :param obj: 查询对象
    :return:
    '''
    if obj is None:
        return jsonify({"status": 404, "message": "数据有误,验证失败!"})


def errors(form):
    '''
    form错误验证
    :param form:
    :return: 错误
    '''
    try:
        return re.findall("\['(.*?)'\]", str(form.errors))[0]
    except:
        return '数据验证错误!'


def add_data(model, Form, db):
    '''
    添加数据
    :param model: 数据模型
    :param Form: Form模型
    :param db: db
    :return: json
    '''
    try:
        obj = model()
        form = Form(request.form)
        if form.validate():
            obj.set_attrs(form.data)
            db.session.add(obj)
        else:
            return jsonify({"status": 1, "message": errors(form)})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库错误!致命"})
    return jsonify({"status": 0})


def batch_add(model, db, data: list):
    """
    批量添加数据
    :param model:  数据模型
    :param db:  db
    :param data:  数据格式:list(dict)
    :return: 0:成功|1:失败
    """
    try:
        for val in data:
            obj = model()
            obj.set_attrs(val)
            db.session.add(obj)
            db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库错误!致命"})
    return None


def spider_add_data(data: dict):
    '''
    采集入库数据
    :param db: db
    '''
    from apps.models.document_model import Document_Model, db
    obj = Document_Model()
    obj.set_attrs(data)
    db.session.add(obj)
    try:
        db.session.commit()
    except:
        db.session.rollback()
        return
    return "采集入库成功"


def edit_data(Form, model, db, uid):
    '''
    修改数据
    :param Form: Form模型
    :param model: 数据模型
    :param db: db
    :param uid: id
    :return: json
    '''
    form = Form(request.form)
    try:
        obj = model.query.filter_by(id=uid).first()
        if form.validate() and not check_obj(obj):
            obj.set_attrs(form.data)
        else:
            return jsonify({"status": 1, "message": errors(form)})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": errors(form)})
    return jsonify({"status": 0})


def recover_data(model, db, uid):
    '''
    恢复数据
    :param model: 数据模型
    :param db: db
    :param uid: id
    :return: json
    '''
    try:
        obj = model.query.filter_by(id=uid).first()
        if not check_obj(obj) and obj:
            obj.set_attrs({"status": 1})
        else:
            return jsonify({"status": 1})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库操作异常!"})
    return jsonify({"status": 0})


def fake_delete_data(model, db, uid):
    '''
    软删除数据
    :param model: 数据模型
    :param db: db
    :param uid: id
    :return: json
    '''
    try:
        obj = model.query.filter_by(id=uid).first()
        if not check_obj(obj) and obj:
            obj.set_attrs({"status": 0})
        else:
            return jsonify({"status": 1})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库操作异常!"})
    return jsonify({"status": 0})


def real_delete_data(model, db, uid):
    '''
    硬删除数据
    :param model: 数据模型
    :param db: db
    :param uid: id
    :return: json
    '''
    try:
        obj = model.query.filter_by(id=uid).first()
        if not check_obj(obj) and obj:
            db.session.delete(obj)
        else:
            return jsonify({"status": 1})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库操作异常!"})
    return jsonify({"status": 0})


def fake_deletes(model, db, uid_s: list):
    '''
    批量软删除
    :param model: 数据模型
    :param db: db
    :param uid_s: ID列表
    :return: json
    '''
    try:
        for uid in uid_s:
            obj = model.query.filter_by(id=uid).first()
            if not check_obj(obj) and uid:
                obj.set_attrs({"status": 0})
            else:
                return jsonify({"status": 1})
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库操作异常!"})
    return jsonify({"status": 0})


def real_deletes(model, db, uid_s: list):
    '''
    批量硬删除
    :param model: 数据模型
    :param db: db
    :param uid_s: ID列表
    :return: json
    '''
    try:
        for uid in uid_s:
            obj = model.query.filter_by(id=uid).first()
            if not check_obj(obj) and uid: db.session.delete(obj)
        db.session.commit()
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "数据库操作异常!"})
    return jsonify({"status": 0})


def member_pwd_edit(model, Form, db, paw_old, id):
    """
    修改密码
    :param model: 数据模型
    :param Form: Form模型
    :param db: db
    :param paw_old: 旧密码
    :param id: id
    :return: json
    """
    try:
        obj = model.query.filter_by(id=id).first()
        form = Form(request.form)
        if form.validate() and not check_obj(obj):  # 原密码输入正确 并验证成功
            if check_password(obj.password, paw_old):
                obj.set_attrs(form.data)
                db.session.commit()
                return jsonify({"status": 0})
            return jsonify({"status": 1, "message": "原密码错误!"})
        return jsonify({"status": 1, "message": errors(form)})
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "密码修改异常!"})


def update_status(model, db, uid, statu):
    """
    启用-停用
    :param model: 数据模型
    :param db: db
    :param uid: id
    :param statu: 标识
    :return: json
    """
    try:
        obj = model.query.filter_by(id=uid).first()
        if not check_obj(obj):
            obj.set_attrs({"status": statu})
            db.session.commit()
            return jsonify({"status": 0})
        return jsonify({"status": 1, "message": "参数非法!"})
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": "操作异常!"})


def initialize(model, db, data: dict = None):
    """
    初始化
    :param model: 数据模型
    :param db: db
    :param data: 数据
    :return:
    """
    try:
        if not model.query.filter().count():
            if data:
                obj = model()
                obj.set_attrs(data)
                db.session.add(obj)  # 初始化系统
                db.session.commit()
                return
            db.session.add(model())  # 初始化系统
            db.session.commit()
    except:
        db.session.rollback()


def log(message: str):  # 日志管理
    from apps.models.system_model import Log_Model, db
    try:
        if message:
            new_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            user = current_user.username
            data = {"detail_time": new_time, "content": '【' + user + '】' + message}
            obj = Log_Model()
            obj.set_attrs(data)
            db.session.add(obj)
            db.session.commit()
    except:
        db.session.rollback()


def page_auto(obj_list):
    '''
    系统分页
    :param obj_list:
    :return: data_list(数据列表),page(分页对象)
    '''
    from apps.setting import Config
    page_interval = Config.PAGE_INTERVAL
    page = int(request.args.get('page', 1))
    paginate = obj_list.paginate(page, page_interval)
    return paginate.items, paginate


def api_edit(Form, model, db, uid):
    '''
    修改api
    :param Form: Form模型
    :param model: 数据模型
    :param db: db
    :param uid: id
    :return: json
    '''
    form = Form(request.form)
    try:
        obj = model.query.filter_by(id=uid).first()
        api_key = request.form.get('api_key')
        if form.validate() and not check_obj(obj):
            data = {"api_ak": "token:" + generate_token(api_key), "api_key": api_key}
            obj.set_attrs(data)
            db.session.commit()
            return jsonify({"status": 0})
        return jsonify({"status": 1, "message": errors(form)})
    except:
        db.session.rollback()
        return jsonify({"status": 1, "message": errors(form)})


def get_hash(string: str):
    '''
    获取一个哈希值
    :param string:
    :return:  哈希字符串
    '''
    ha = hashlib.md5()
    ha.update(string.encode('utf-8'))
    ha_str = ha.hexdigest()
    return ha_str


def web_page_auto(obj_list):
    '''
    系统前台分页
    :param obj_list:
    :return: data_list(数据列表),page(分页对象)
    '''
    from apps.setting import Config
    page_interval = Config.WEB_PAGE_INTERVAL
    page = int(request.args.get('page', 1))
    paginate = obj_list.paginate(page, page_interval)
    return paginate.items, paginate


def webApp_check(fun):
    '''
    验证站点是否启用
    :param fun:
    :return:
    '''

    def inner(*args, **kwargs):
        from apps.models.system_model import System_Model
        obj = System_Model.query.first()
        if not obj.web_on_off: return f'<div><h2 style="text-align: center;">站点已关闭! 联系管理员QQ:{obj.web_contact_qq}</h2></div>'
        new_fun = fun(*args, **kwargs)
        return new_fun

    return inner
